#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>	/* printk() */

#include <linux/types.h>
#include <linux/fs.h>
#include <linux/kdev_t.h>
#include <linux/cdev.h>

typedef struct 
{
	dev_t dev_no;
	struct cdev cdev;
	struct file_operations *fops;
	unsigned int dev_count;
	char *name;
	char *pmem;
}mem_cdev_t;

int mem_open(struct inode *inode, struct file *filp)
{
	printk(KERN_INFO "mem_open\n");
	return 0;
}
int mem_release(struct inode *inode, struct file *filp)
{
	printk(KERN_INFO "mem_release\n");
	return 0;
}
struct file_operations fops=
{
	.owner = THIS_MODULE,
	.open = mem_open,
	.release = mem_release,
};

mem_cdev_t mem_cdev=
{
	.cdev.owner = THIS_MODULE,
	.fops = &fops,
	.name = "mem_dev",
	.dev_count = 1,
};


MODULE_AUTHOR("suser");
MODULE_LICENSE("Dual BSD/GPL");

static void __exit hello_exit(void)
{
	
	unregister_chrdev(MAJOR(mem_cdev.dev_no),mem_cdev.name);
	cdev_del(&mem_cdev.cdev);
	unregister_chrdev_region(mem_cdev.dev_no, 1);
	printk(KERN_ALERT "good bye\n");
}

static int __init hello_init(void)
{
	int ret = 0;
	if(alloc_chrdev_region(&mem_cdev.dev_no, 0, 1, mem_cdev.name))
	{
		printk(KERN_INFO "failed to alloc dev no.\n");
		goto dev_no_err_out;
	}
	else
	{
		printk(KERN_INFO "major:%d minor:%d\n",MAJOR(mem_cdev.dev_no),MINOR(mem_cdev.dev_no));
	}
	cdev_init(&mem_cdev.cdev, mem_cdev.fops);
	ret = cdev_add(&mem_cdev.cdev, mem_cdev.dev_no, 1);
	if (ret < 0)
	{
		printk(KERN_INFO "failed to add chrdev\n");
		goto cdev_add_err_out;
	}
	printk(KERN_ALERT "hello world\n");	

	return 0;
cdev_add_err_out:	
	cdev_del(&mem_cdev.cdev);
	printk(KERN_INFO "cdev_del_err\n");
dev_no_err_out:	
	unregister_chrdev_region(mem_cdev.dev_no, 1);
	printk(KERN_INFO "dev_no_err\n");
	return -1;
}


module_init(hello_init);
module_exit(hello_exit);
	
